package cn.gogoyc.org.basic.servie.impl;

import cn.gogoyc.org.basic.dto.PhoneCodeDto;
import cn.gogoyc.org.basic.exception.BusinessException;
import cn.gogoyc.org.basic.servie.VerifyCodeService;
import cn.gogoyc.org.basic.util.AjaxResult;
import cn.gogoyc.org.basic.util.StrUtils;
import cn.gogoyc.org.basic.util.VerifyCodeUtils;
import cn.gogoyc.user.domain.User;
import cn.gogoyc.user.mapper.UserMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 验证码业务层
 *
 * @author Yang
 * @date 2023 /2/7 16:48
 */
@Service
public class VerifyCodeServiceImpl implements VerifyCodeService {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    /**
     * 图形验证码生成及Redis存储
     * @param key
     * @return
     */
    @Override
    public String getImageCode(String key) {
        //使用工具类生成四个随机字母
        String code = StrUtils.getComplexRandomString(4);
        //将这个前端传过来的key(UUID)和生成的四个字母设置进redis,时效为五分钟
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);
        //然后将这个code使用工具类加工变成base64图片编码返回给接口
        return VerifyCodeUtils.verifyCode(115,40,code);
    }

    /**
     * 手机验证码生成及Redis存储
     * @param dto
     */
    @Override
    public void getPhoneCode(PhoneCodeDto dto) {
        //前端传来的手机和验证码空值判断
        if (StringUtils.isEmpty(dto.getPhone()) || StringUtils.isEmpty(dto.getImageCode())){
            //若空值异常弹窗提醒
            throw new BusinessException("信息不能为空!");
        }


        //根据电话查询对象
        User user = userMapper.loadByPhone(dto.getPhone());
        //查询数据库是否有这个对象,!=null是注册过
        if (user != null){
            //若注册过弹窗提醒
            throw new BusinessException("您已注册过,请直接去登录!");
        }

        //根据key(UUID)查询对应的验证码判断是否过期
        Object obj = redisTemplate.opsForValue().get(dto.getImageCodeKey());
        if (obj == null){
            //验证码过期则弹窗提醒
            throw new BusinessException("图形验证码已过期,请刷新!");
        }

        //判断前端输入的验证码和redis中的验证码是否相等
        if (!dto.getImageCode().equalsIgnoreCase(obj.toString())){
            //若不相同则弹窗提醒
            throw new BusinessException("图形验证码不一致,请正确输入!");
        }

        //根据key去获取value 该key是拼接了业务键用于区分注册和登录
        //第一次肯定是null
        Object phoneCodeObj = redisTemplate.opsForValue().get("register:" + dto.getPhone());
        String phoneCode = null;
        //如果该value没有值
        if (phoneCodeObj == null){
            //则生成验证码赋值
             phoneCode = StrUtils.getRandomString(4);
        }else {
            //如果该key有值(有验证码)
            //获取当前时间毫秒值
            Long now = System.currentTimeMillis();
            //将Value转为字符串根据:号切割成一个String数组,[0]则是验证码,[1]则是时间戳
            Long old = Long.parseLong(phoneCodeObj.toString().split(":")[1]);

            //当前时间戳减去key的时间戳 如果大于60秒的话
            if ((now-old) >1*60*1000){
                //则弹窗提醒,说明它在频繁点击
                throw new BusinessException("请勿频繁获取验证码!");
            }else {
                //如果大于60秒则拿到切割好后的验证码复制给变量验证码
                phoneCode = phoneCodeObj.toString().split(":")[0];
            }
        }

        //覆盖赋值刷新时间,key=register手机号 value=手机验证码+当前时间戳
        //还是原来的验证码,如果三分钟过期后则生成新的验证码
        redisTemplate.opsForValue().set("register:"+dto.getPhone(),
                phoneCode+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);

        /*SmsUtils.sendSms("19150662981","您的验证码为"+phoneCode+",三分钟内有效哦!");*/
        System.out.println("您的验证码为"+phoneCode+",三分钟内有效哦!");
    }

    /**
     * 微信用户第一次登录的注册页面验证码处理
     * @param dto
     */
    @Override
    public void getBinderSmsCode(PhoneCodeDto dto) {
        //前端传来的手机和验证码空值判断
        if (StringUtils.isEmpty(dto.getPhone())){
            //若空值异常弹窗提醒
            throw new BusinessException("手机号不能为空!");
        }


        //根据key去获取value 该key是拼接了业务键用于区分注册和登录
        //第一次肯定是null
        Object phoneCodeObj = redisTemplate.opsForValue().get("binder:" + dto.getPhone());
        String phoneCode = null;
        //如果该value没有值
        if (phoneCodeObj == null){
            //则生成验证码赋值
            phoneCode = StrUtils.getRandomString(4);
        }else {
            //如果该key有值(有验证码)
            //获取当前时间毫秒值
            Long now = System.currentTimeMillis();
            //将Value转为字符串根据:号切割成一个String数组,[0]则是验证码,[1]则是时间戳
            Long old = Long.parseLong(phoneCodeObj.toString().split(":")[1]);

            //当前时间戳减去key的时间戳 如果大于60秒的话
            if ((now-old) >1*60*1000){
                //则弹窗提醒,说明它在频繁点击
                throw new BusinessException("请勿频繁获取验证码!");
            }else {
                //如果大于60秒则拿到切割好后的验证码复制给变量验证码
                phoneCode = phoneCodeObj.toString().split(":")[0];
            }
        }

        //覆盖赋值刷新时间,key=register手机号 value=手机验证码+当前时间戳
        //还是原来的验证码,如果三分钟过期后则生成新的验证码
        //第一次点击获取验证码直接将获取到的验证码入库
        redisTemplate.opsForValue().set("binder:"+dto.getPhone(),
                phoneCode+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);

        /*SmsUtils.sendSms("19150662981","您的验证码为"+phoneCode+",三分钟内有效哦!");*/
        System.out.println("您的验证码为"+phoneCode+",三分钟内有效哦!");
    }

}
